from functools import wraps

from ..job_store.interface import JobDoneUpdateModel, JobRunTimesUpdateModel
from .interface import AddOrRunTimer, JobRetryPolicy, Job, policy_pool


class OneOffJob(JobRetryPolicy):
    '''
    一次性任务, 无论执行成功与否, 不进行重试
    '''
    def retry(self, tw: AddOrRunTimer):
        def inner(func):
            @wraps(func)
            def inner(timer: Job):
                done = func(timer)
                timer.run_times += 1
                timer.done = 1
                m = JobDoneUpdateModel(**timer.dict())
                try:
                    self.job_store.done(timer.job_id, m)
                except Exception as err:
                    print(err)
                return done
            return inner
        return inner

    @classmethod
    def name(cls) -> str:
        return 'one_off_job'


class JobRetryIncreaseProgressively(JobRetryPolicy):
    """任务重试N次"""
    _max_retry_times = 10

    def __init__(self, max_retry_times: int = None):
        if isinstance(max_retry_times, int) and max_retry_times > 0:
            self._max_retry_times = max_retry_times

    @property
    def max_retry_times(self) -> int:
        '''任务最大重试次数'''
        return self._max_retry_times

    def retry(self, tw: AddOrRunTimer):
        def inner(func):
            @wraps(func)
            def inner(timer: Job):
                done = func(timer)
                if done is not True:
                    timer.run_times += 1
                    if timer.run_times >= self.max_retry_times:
                        timer.done = 1
                        m = JobDoneUpdateModel(**timer.dict())
                        self.job_store.done(timer.job_id, m)
                    else:
                        timer.expiration = timer.expiration + timer.run_times * 1000
                        tw.add_or_run(timer)
                        m = JobRunTimesUpdateModel(**timer.dict())
                        self.job_store.update_run_times(timer.job_id, m)
                return done
            return inner
        return inner
    
    @classmethod
    def name(cls) -> str:
        return 'retry_increase_progressively'


policy_pool.register(OneOffJob)
policy_pool.register(JobRetryIncreaseProgressively)